package com.zcoj.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zcoj.mapper.JudgeMapper;
import com.zcoj.mapper.ProblemMapper;
import com.zcoj.mapper.UserMapper;
import com.zcoj.pojo.Dto.Judge;
import com.zcoj.pojo.Dto.Problem;
import com.zcoj.pojo.Dto.User;
import com.zcoj.pojo.Dto.UserAcProblem;
import com.zcoj.pojo.Vo.RankVo;
import com.zcoj.service.RankService;
import com.zcoj.service.UserAcProblemService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author chenbin
 * @version 1.0
 * @description: TODO
 * @date 2023/5/12 15:22
 */
@Service
public class RankServiceImpl implements RankService {
    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserAcProblemService userAcProblemService;

    @Autowired
    private ProblemMapper problemMapper;

    @Autowired
    private JudgeMapper judgeMapper;


    @Override
    public List<RankVo> getAllRank() {
        QueryWrapper<User> userQueryWrapper=new QueryWrapper<>();
        userQueryWrapper.select("id","username","email","oi_score","face_url")
                .orderByDesc("oi_score")
                .last("limit 50");
        List<User> users = userMapper.selectList(userQueryWrapper);
        List<RankVo> rankVoList=new ArrayList<>();

        for (User user : users) {
            RankVo rankVo = new RankVo();
            rankVo.setUsername(user.getUsername());
            rankVo.setAvatar(user.getFaceUrl());
            rankVo.setOIScore(user.getOiScore());
            rankVo.setEmail(user.getEmail());
            QueryWrapper<Judge> judgeQueryWrapper=new QueryWrapper<>();
            judgeQueryWrapper.eq("uid",user.getId());
            Integer submitNum = judgeMapper.selectCount(judgeQueryWrapper);
            rankVo.setSubmitNum(submitNum);
            judgeQueryWrapper.eq("status",0);
            Integer accessNum = judgeMapper.selectCount(judgeQueryWrapper);
            rankVo.setAccessNum(accessNum);
            rankVoList.add(rankVo);
        }

        rankVoList.sort(new Comparator<RankVo>() {
            @Override
            public int compare(RankVo o1, RankVo o2) {
                // 按OiScore从大到小排序
                return o2.getOIScore().compareTo(o1.getOIScore());
            }
        });
        return rankVoList;
    }

    @Override
    public List<RankVo> getRecentWeekRank() {
        Date date = new Date();
        QueryWrapper<Judge> judgeQueryWrapper=new QueryWrapper<>();
        judgeQueryWrapper.ge("create_time", DateUtil.lastWeek())
                .le("create_time",date)
                .eq("status",0);
        List<Judge> judgeList = judgeMapper.selectList(judgeQueryWrapper);
        Set<Integer> userIds=new HashSet<>();
        for (Judge judge : judgeList) {
            userIds.add(judge.getUid());
        }

        List<RankVo> rankVoList=new ArrayList<>();

        for (Integer userId : userIds) {
            RankVo rankVo = new RankVo();
            judgeQueryWrapper.clear();
            judgeQueryWrapper.ge("create_time", DateUtil.lastWeek())
                    .le("create_time",date)
                    .eq("status",0)
                    .eq("uid",userId);
            Integer acc = judgeMapper.selectCount(judgeQueryWrapper);
            rankVo.setAccessNum(acc);

            QueryWrapper<User> userQueryWrapper=new QueryWrapper<>();
            userQueryWrapper.select("face_url","username").eq("id",userId);
            User user = userMapper.selectOne(userQueryWrapper);
            if(Objects.nonNull(user)){
                rankVo.setAvatar(user.getFaceUrl());
                rankVo.setUsername(user.getUsername());
                rankVoList.add(rankVo);
            }
        }

        rankVoList.sort(new Comparator<RankVo>() {
            @Override
            public int compare(RankVo o1, RankVo o2) {
                return o2.getAccessNum()-o1.getAccessNum();
            }
        });


        return rankVoList;
    }

    @Override
    public void calculateOiRank(){
        QueryWrapper<User> userQueryWrapper=new QueryWrapper<>();
        userQueryWrapper.select("id");
        List<User> users = userMapper.selectList(userQueryWrapper);
        for (User user : users) {
            UserAcProblem userAcProblem = new UserAcProblem();
            userAcProblem.setUid(user.getId());
            List<UserAcProblem> userAcProblemServiceList = userAcProblemService.findList(userAcProblem);
            int oiScore=0;

            for (UserAcProblem acProblem : userAcProblemServiceList) {
                QueryWrapper<Problem> problemQueryWrapper=new QueryWrapper<>();
                problemQueryWrapper.select("id","difficulty","oi_score").eq("id",acProblem.getPid());
                Problem problem = problemMapper.selectOne(problemQueryWrapper);
                if( Objects.nonNull(problem)){
                    oiScore+=(problem.getOiScore()*0.1+problem.getDifficulty()*2);
                }
            }
            user.setOiScore(oiScore);
            userMapper.updateById(user);
        }
    }
}
